# coding=utf-8
from PyQt5.QtWidgets import QAbstractItemView, QListWidget, QListWidgetItem, QGraphicsPixmapItem
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class ListWidgetItem(QListWidgetItem):
    image: QImage = None  # 与算法交互的Image
    # 组件
    layerType = 'pixmap'  # 图层类型
    graphicsItem = None  # 在场景中的图元

    controller = None  # 控制器
    # 图层效果
    compositionMode = 0  # 混合模式
    alpha = 100  # alpha
    isEditing = False  # 正在编辑， 一般是进行变换时

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFlags(Qt.ItemIsSelectable
                      | Qt.ItemIsEditable
                      | Qt.ItemIsUserCheckable
                      | Qt.ItemIsEnabled
                      | Qt.ItemIsDragEnabled
                      | Qt.ItemIsDropEnabled
                      )

    def updateImage(self):
        """
        将 graphics 的 变换(主要是几何变换) 更新到ImageData，以便和外部进行算法交互
        :return:
        """
        if self.layerType == 'pixmap':
            graphicsItem = self.graphicsItem
            pixmap = graphicsItem.pixmap()
            self.image = pixmap.toImage().transformed(graphicsItem.transform())

    def updatePixmap(self, image=None):
        """
        将 para:image（同时会更新当前image数据） 或者 graphics 的 ImageLayerList 的 image 数据替换现有的pixmap，同时清除graphics现有的所有变换
        :return:
        """
        if self.layerType == 'pixmap':
            graphicsItem = self.graphicsItem
            # 记录位置
            anchor = graphicsItem.sceneBoundingRect().topLeft()
            graphicsItem.resetTransform()
            if image:
                graphicsItem.setPixmap(QPixmap.fromImage(image))
                self.image = image
            else:
                graphicsItem.setPixmap(QPixmap.fromImage(self.image))
            # graphicsItem.setPos(anchor.xRate()-1, anchor.yRate() - 1)  # sceneBoundingRect有1个单位的宽度
            graphicsItem.setPos(anchor.x(), anchor.y())  # sceneBoundingRect有1个单位的宽度

    def aboutSave(self):
        if self.controller:
            self.controller.aboutSave()


class ListWidget(QListWidget):
    imageWindow = None  # 工作区 窗体
    previous = None  # 前一个选择的列表项目
    # 图层 显示 隐藏
    color = {
        'background': QColor(88, 88, 88),
        'foreground': QColor(245, 245, 245),
        'background-hide': QColor(10, 10, 10),
        'foreground-hide': QColor(100, 100, 100),
    }
    # 图层类型
    layerDefaultType = ''
    layerDefaultIcon = {}
    # 字体
    font = QFont()
    font.setPointSize(12)
    # 信号
    currentItemChanged = pyqtSignal(list)  # 选择图层信号
    itemRowChanged = pyqtSignal()  # 图层顺序改变信号

    def __init__(self, parent):
        super().__init__(parent)
        self.Ui_init()
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.show()

    def Ui_init(self):
        self.setIconSize(QSize(70, 70))
        # 特性
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setDefaultDropAction(Qt.MoveAction)
        self.setDragDropOverwriteMode(True)
        # self.showDropIndicator()

    def showLayer(self, listItem, show):
        """
        show the item
        :param listItem: QListWidgetItem
        :param show: boolean
        :return:
        """
        if listItem.show == show:
            return
        if show:
            listItem.setBackground(self.color['background'])
            listItem.setForeground(self.color['foreground'])

        else:
            listItem.setBackground(self.color['background-hide'])
            listItem.setForeground(self.color['foreground-hide'])
        listItem.show = show
        # 场景中的 图元
        graphicsItem = listItem.graphicsItem
        if graphicsItem:
            graphicsItem.setVisible(show)
            print('吟唱')

    def newLayer(self, info=None):
        """
        create a new imageLayer
        the imageLayer will be format by the info of [dic info]
        :param info:
        info = {
            'name',str
            'image': if the layerType is pixmap, this is required
            'graphicsItem',QGaphicsItem
            'layerType', str and one of [pixmap,text,shape]
            'icon',QIcon
            'index',int
        }
        :return:QListWidgetItem  the new ListItem of the new imageLayer
        """
        newListItem = ListWidgetItem()
        newListItem.setFont(self.font)
        newListItem.setTextAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        # 名字
        name = info.get('name')
        if name is None:
            name = '图层 ' + str(self.count())
        newListItem.setText(name)
        # 图元
        graphicsItem = info.get('graphicsItem')
        newListItem.graphicsItem = graphicsItem

        # 图层类型
        layerType = info.get('layerType', 'pixmap')
        newListItem.layerType = layerType
        # 图像数据
        if layerType == 'pixmap':
            newListItem.image = info.get('image', None)

        # 图标
        icon = info.get('icon')
        if not isinstance(icon, QIcon):
            icon = self.layerDefaultIcon[layerType]
        newListItem.setIcon(icon)
        # 插入位置
        index = info.get('index')
        if index is None:
            index = self.currentRow()
            if index > 0:
                index = index - 1

        self.insertItem(index, newListItem)
        newListItem.show = True
        # 发射图层顺序改变信号
        self.itemRowChanged.emit()
        return newListItem

    def removeLayer(self, listItem):
        if listItem:
            # 移除场景中的 图元
            graphicsItem = listItem.graphicsItem
            if graphicsItem:
                scene = self.imageWindow.scene
                scene.removeItem(graphicsItem)
                del graphicsItem
            # 移除列表项目
            print('移除', listItem.text())
            self.takeItem(self.row(listItem))
            self.removeItemWidget(listItem)
            del listItem
            self.itemRowChanged.emit()

    @property
    def previousItem(self):
        """
        上一次选择的项目
        :return:
        """
        return self.previous

    @property
    def getSelectedItems(self):
        """
        get all items selecter
        :return: QList
        """
        return self.selectedItems()

    @property
    def allItems(self):
        """
        return all QListWidgetItem
        :return: list of QListWidgetItem
        """
        ret = []
        for row in range(0, self.count()):
            ret.append(self.item(row))
        return ret
